<template>
	<view class="">
		<Header
			:title="headerTitle"
			:showRight="showRight"
			:titleSize="20"
			:Righttext="t('history')"
			rightColor="#999"
			:rightSize="12"
			@rightClick="goHistory" />
		<view class="scroll">
			<scroll-view
				scroll-y
				:scroll-into-view="'list-' + selTimezone"
				class="scroll-box">
				<up-list
					class="cell-list"
					v-if="errorList.length && !isLoading">
					<up-list-item
						v-for="(item, index) in errorList"
						:key="`item-${index}`">
						<up-cell @longpress="copyItem(item)">
							<template #icon>
								<up-avatar
									shape="square"
									size="48"
									:src="
										'/static/image/info/' +
										(item.code != 4214002
											? 'error.png'
											: 'right.png')
									"></up-avatar>
							</template>
							<template #title>
								<view class="tilte-box">
									<view class="top-box">
										<view class="title">
											<text v-if="item.code != 4214002">
												{{ getEventDisplay(item.code) }}
											</text>
											<text v-else>
												{{ t("error.release") }}
											</text>
										</view>
										<text class="time">
											{{ formatTime(item?.create_time) }}
										</text>
									</view>
									<view class="tag-box">
										<up-tag :text="item.code"></up-tag>
										<up-tag
											:text="
												getEventLevel(item.code) ||
												item.code
											"></up-tag>
										<up-tag :text="item.exist"></up-tag>
									</view>
									<view class="bottom-text">
										<text
											v-if="
												headerType === 'realTimeError'
											">
											{{
												item.device_name
													? item.device_name +
													  " " +
													  (getEventInfo(
															item.code
													  ) || item.msg)
													: item.device_sn +
													  " " +
													  (getEventInfo(
															item.code
													  ) || item.msg)
											}}
										</text>
										<text v-else>
											{{
												item.code != 4214002
													? getEventInfo(item.code) ||
													  item.msg
													: parseMsg(item.msg)
											}}
										</text>
									</view>
								</view>
							</template>
						</up-cell>
					</up-list-item>
				</up-list>
				<view class="loading" v-show="isLoading">
					<LoadingDots />
				</view>
				<view class="no-more" v-if="errorList.length && isLoadMore">
					{{ t("noMore") }}
				</view>
				<up-empty
					v-if="!errorList.length && !isLoading"
					icon="/static/image/common/noData.svg"
					width="35%"
					textSize="18"
					text-color="#b8b8b8"
					safeAreaInsetBottom
					:text="t('noList')"></up-empty>
			</scroll-view>
		</view>
	</view>
</template>

<script setup lang="ts">
import Header from "@/components/header/index.vue";
import { onMounted, ref, getCurrentInstance, computed } from "vue";
import {
	onReachBottom,
	onLoad,
	onPullDownRefresh,
	onShow,
	onHide,
} from "@dcloudio/uni-app";
import { getMsg, getEventApi, getEventExist } from "@/service/index";
import LoadingDots from "@/components/LoadingDots/index.vue";
import parseMsg from "@/components/infoList/parseMsg";
import moment from "moment-timezone";
import { useI18n } from "vue-i18n";
const { t } = useI18n();
interface errItem {
	code?: number;
	create_time?: number | string;
	device_name?: string;
	device_sn?: string;
	event_id?: number;
	[key: string]: any;
}
interface ErrorCode {
	[key: string]: string;
}
interface ErrorCodeItem {
	code: number | string;
	class?: string;
	define?: string;
	[key: string]: string;
}
const instance: any = getCurrentInstance();
const selTimezone = ref<number>(0);
const headerTitle = ref(t("message.title.2"));
const timeZoneStore = useUniversalStorage<string>(
	"SELECTED_TIMEZONE",
	"Asia/Shanghai"
);
const showRight = ref(false);
const topHeight = ref("0");
const isLoading = ref(false);
const isLoadMore = ref(false);
const codeJson = ref<ErrorCode>({});
const errorList = ref<errItem[]>([]);
const headerType = ref("");
const query = ref({
	page: 1,
	size: 10,
	type: "error",
	device_sn: "",
});
const getErrorList = async () => {
	try {
		isLoading.value = true;
		const { data } = await getEventApi(query.value);
		if (data?.code === 0) {
			if (data.data.length > 0) {
				if (query.value.page === 1) {
					errorList.value = data.data;
				} else {
					errorList.value = [...errorList.value, ...data.data];
				}
				query.value.page += 1;
			} else {
				if (query.value.page === 1) {
					errorList.value = [];
				}
				isLoadMore.value = true;
			}
		} else {
			instance.proxy.$message(
				data?.msg || t("request.failed"),
				"warning"
			);
		}
	} catch (error) {
		instance.proxy.$message("网络请求异常", "error");
	} finally {
		isLoading.value = false;
	}
};
interface CopyConfig {
	device: string;
	code: string;
	level: string;
	desc: string;
	successMsg: string;
}
// 构建复制内容
const buildCopyContent = (item: errItem): string => {
	const config: CopyConfig = {
		device: t("copy.device"),
		code: t("copy.code"),
		level: t("copy.level"),
		desc: t("copy.desc"),
		successMsg: "复制成功",
	};
	const eventDisplay = getEventDisplay(item.code) || "未知";
	const eventInfo = getEventInfo(item.code) || item.msg || "无描述";

	return `${config.device}：${item.device_sn}
${config.code}：${item.code}
${config.level}：${eventDisplay}
${config.desc}：${eventInfo}`;
};
const copyItem = (item: errItem) => {
	try {
		// 验证输入
		if (!item || !item.device_sn || !item.code) {
			instance.proxy.$message("复制失败: 缺少必要字段", "error");
			return;
		}
		// 构建复制内容
		const copyContent = buildCopyContent(item);
		// 执行复制
		uni.setClipboardData({
			data: copyContent,
			success: () => {
				uni.showToast({
					title: t("copyOk"),
					icon: "success",
					duration: 2000,
				});
				// instance.proxy?.$message?.("复制成功", "success");
			},
			fail: (error) => {
				console.log(error);
				uni.showToast({
					title: error.errMsg || "复制失败",
					icon: "none",
					duration: 3000,
				});
				// instance.proxy?.$message?.(error, "warning");
			},
		});
	} catch (error) {
		console.error("复制操作异常:", error);
	}
};
const isAddZero = (time: number): string => time.toString().padStart(2, "0");
const formatTime = (time: number | string): string => {
	try {
		if (timeZoneStore.value) {
			// 处理时间戳
			const timestamp = Math.floor(Number(time) / 1000);
			if (!timestamp) return "";

			const createTime = moment.unix(timestamp).tz(timeZoneStore.value);
			return createTime.isValid()
				? createTime.format("MM-DD HH:mm:ss")
				: "";
		} else {
			// 本地时间处理
			const date = new Date(time);
			if (isNaN(date.getTime())) return "";
			const month = (date.getMonth() + 1).toString().padStart(2, "0");
			const day = date.getDate().toString().padStart(2, "0");
			const hours = date.getHours().toString().padStart(2, "0");
			const minutes = date.getMinutes().toString().padStart(2, "0");
			const seconds = date.getSeconds().toString().padStart(2, "0");
			return `${month}-${day} ${hours}:${minutes}:${seconds}`;
		}
	} catch (error) {
		console.error("时间格式化错误:", error);
		return "";
	}
};
const normalizeCode = (code: number | string): number => {
	try {
		const codeStr = String(code).trim();
		if (codeStr.length <= 1) return 0;
		const num = Number(codeStr.substring(1));
		return isNaN(num) ? 0 : num;
	} catch {
		return 0;
	}
};
const getEventLevel = (code: number | string): string => {
	const codeMap: Record<string, string> = {
		"1": "message.code1",
		"2": "message.code2",
		"3": "message.code3",
		"4": "message.code4",
	};

	const firstChar = String(code).charAt(0);
	const messageKey = codeMap[firstChar] || "message.unknownCode";

	return t(messageKey);
};
// 创建代码映射表，避免在列表渲染中重复计算
const codeMap = computed(() => {
	const map = new Map<number, ErrorCodeItem>();

	// 验证数据源
	if (!codeJson.value) {
		return map;
	}

	// 处理非数组情况
	const safeArray = Array.isArray(codeJson.value)
		? codeJson.value
		: Object.values(codeJson.value);

	// 填充映射表
	safeArray.forEach((item: any) => {
		if (!item?.code) return;

		const key = normalizeCode(item.code);
		if (key > 0) {
			map.set(key, item);
		}
	});

	return map;
});
// 获取事件显示文本
const getEventDisplay = (code: number | string): string => {
	if (code === 4214002) return "";
	const normalizedCode = normalizeCode(code);
	if (normalizedCode === 0) return "Invalid Code";

	const matchedItem = codeMap.value.get(normalizedCode);

	if (matchedItem?.class && matchedItem?.define) {
		return `${matchedItem.class}-${matchedItem.define}`;
	}
	return t("message.NoerrorCode");
};
const getEventInfo = (code: number | string) => {
	if (
		!codeJson.value ||
		!Array.isArray(codeJson.value) ||
		codeJson.value.length === 0
	) {
		return "";
	}
	if (!code && code !== 0) {
		return "";
	}
	const normalizeCode = (codeValue: number | string): number => {
		const codeStr = String(codeValue);
		if (codeStr.length <= 1) return 0;
		return Number(codeStr.substring(1)) || 0;
	};
	const targetCode = normalizeCode(code);
	if (targetCode === 0) return "";
	const matchedItem = codeJson.value.find((ele) => {
		if (!ele?.code && ele?.code !== 0) return false;
		return normalizeCode(ele.code) === targetCode;
	});

	return matchedItem?.info || "";
};
// 获取请求 URL
const getRequestUrl = (): string => {
	const langSuffix = useUniversalStorage<string>("LOCALE", "zh");
	const baseFileName = `anomaly_${langSuffix.value}.json`;

	// #ifdef H5
	return `http://39.108.167.56/downloads/config/event/${baseFileName}`;
	// #endif

	// #ifdef APP-PLUS
	return `https://paas.jtcx.cn/downloads/config/event/${baseFileName}`;
	// #endif
	// 默认返回（开发环境）
	return `http://39.108.167.56/downloads/config/event/${baseFileName}`;
};
const getCodeJson = async () => {
	try {
		const url = getRequestUrl();
		const response = await uni.request({
			url,
			method: "GET",
			header: {
				"content-type": "application/json",
			},
			timeout: 10000, // 10秒超时
		});
		if (response.statusCode === 200) {
			codeJson.value = response.data as ErrorCode;
		} else {
			instance.proxy.$message(response.errMsg, "error");
		}
	} catch (err) {
		// const errorMessage = err instanceof Error ? err.message : "未知错误";
		// instance.proxy.$message(errorMessage, "error");
	} finally {
		isLoading.value = false;
	}
};
onMounted(() => {
	// 获取状态栏高度
	// #ifdef APP-PLUS
	const statusBarHeight = ref(0);
	const systemInfo = uni.getSystemInfoSync();
	statusBarHeight.value = systemInfo.statusBarHeight || 0;
	topHeight.value = statusBarHeight.value + "px";
	// #endif
});

interface QueryParams {
	page: number;
	size: number;
	device_sn?: string;
	type: string;
}

interface ApiResponse {
	code: number;
	data: errItem[];
	message?: string;
}

// 响应式数据

// 轮询相关
const pollingInterval = ref<NodeJS.Timeout | null>(null);
const isPolling = ref(false);
const errorCount = ref(0);
const MAX_ERROR_COUNT = 3;

/**
 * 过滤重复事件，保留最新的记录
 */
const filterDuplicateEvents = (events: errItem[]): errItem[] => {
	const eventMap = new Map<string | number, errItem>();

	events.forEach((event) => {
		// 跳过特定代码
		if (event.code === 4214002) return;

		const existingEvent = eventMap.get(event.code);

		if (!existingEvent) {
			eventMap.set(event.code, event);
		} else {
			// 比较时间，保留较新的记录
			const currentTime = new Date(event.create_time).getTime();
			const existingTime = new Date(existingEvent.create_time).getTime();

			if (currentTime > existingTime) {
				eventMap.set(event.code, event);
			}
		}
	});

	return Array.from(eventMap.values());
};

/**
 * 检查事件列表是否相同（深度比较）
 */
const isEventListEqual = (list1: errItem[], list2: errItem[]): boolean => {
	if (list1.length !== list2.length) return false;

	return list1.every((event, index) => {
		const otherEvent = list2[index];
		return (
			event.code === otherEvent.code &&
			event.create_time === otherEvent.create_time
		);
	});
};

/**
 * 构建轮询查询参数
 */
const buildPollingQuery = (): QueryParams => {
	const currentLength = errorList.value.length;
	const currentPage = Math.ceil(currentLength / query.value.size);

	return {
		page: 1,
		size: query.value.page * query.value.size, // 动态计算需要获取的数量
		device_sn: query.value.device_sn,
		type: headerType.value === "repair" ? "repair" : "error",
	};
};

/**
 * 轮询获取事件数据
 */
const startPolling = async (): Promise<void> => {
	if (isPolling.value) {
		console.warn("轮询已在进行中");
		return;
	}

	isPolling.value = true;

	try {
		const pollingQuery = buildPollingQuery();
		const response = await getEventExist(pollingQuery);

		if (response.data?.code === 0) {
			errorCount.value = 0; // 重置错误计数

			const rawData = response.data.data || [];

			if (rawData.length > 0) {
				const filteredData = filterDuplicateEvents(rawData);

				// 只有数据不同时才更新
				if (
					!isEventListEqual(errorList.value, filteredData) &&
					headerType.value !== "error"
				) {
					errorList.value = filteredData;
				}
			} else {
				// 清空数据
				errorList.value = [];
			}
		} else {
			throw new Error(`API 返回错误码: ${response.data?.code}`);
		}
	} catch (error) {
		errorCount.value++;
		// 错误次数过多时停止轮询
		if (errorCount.value >= MAX_ERROR_COUNT) {
			stopPolling();
		}
	} finally {
		isPolling.value = false;
	}
};

/**
 * 开始定时轮询
 */
const startPollingInterval = (interval: number = 5000): void => {
	if (pollingInterval.value) {
		stopPolling();
	}

	// 立即执行一次
	startPolling();

	pollingInterval.value = setInterval(async () => {
		await startPolling();
	}, interval);

	console.log(`轮询已启动，间隔: ${interval}ms`);
};

/**
 * 停止轮询
 */
const stopPolling = (): void => {
	if (pollingInterval.value) {
		clearInterval(pollingInterval.value);
		pollingInterval.value = null;
		isPolling.value = false;
	}
};

/**
 * 重置轮询
 */
const resetPolling = (): void => {
	stopPolling();
	errorList.value = [];
	errorCount.value = 0;
};
const goHistory = () => {
	uni.navigateTo({
		url: `/pages/manage/errorMessage?device_sn=${query.value.device_sn}&&type=error`,
	});
};
const getInfo = () => {
	switch (headerType.value) {
		case "realTimeError":
			headerTitle.value = t("message.title.3");
			showRight.value = true;
			startPollingInterval();
			break;
		case "error":
			headerTitle.value = t("message.title.1");
			getErrorList();
			break;
		default:
			headerTitle.value = t("message.title.2");
			startPollingInterval();
			break;
	}
};
// 获取当前页面参数
const getCurrentPageOptions = (): Record<string, any> => {
	const pages = getCurrentPages();
	if (pages.length === 0) {
		console.log("页面栈为空");
		return {};
	}

	const currentPage: any = pages[pages.length - 1];
	let params: Record<string, any> = {};
	// #ifdef APP-PLUS
	if (currentPage.$page && currentPage.$page.options) {
		params = currentPage.$page.options;
	}
	// #endif
	// #ifdef H5
	if (currentPage.$route && currentPage.$route.query) {
		params = currentPage.$route.query;
	}
	// #endif
	return params;
};
onShow(async () => {
	const options = getCurrentPageOptions();
	if (options?.device_sn) {
		query.value.device_sn = options.device_sn;
		headerType.value = options?.type;
		getCodeJson();
		getInfo();
	}
});
onHide(() => {
	resetPolling();
});
</script>

<style lang="scss" scoped>
.scroll {
	width: 100%;
	z-index: -1;
	height: 100vh;
	background-color: #fff;
	// #ifdef APP-PLUS
	// padding-top: v-bind(topHeight);
	// #endif
}
.cell-list {
	:deep(.u-cell__body) {
		padding: 0 10px 14px !important;
	}
	:deep(.u-line) {
		border-bottom: 1px solid #f5f6f7 !important;
	}
	.tilte-box {
		display: flex;
		flex-direction: column;
		padding-top: 14px;
		padding-left: 15px;
		gap: 5px;
		.tag-box {
			display: flex;
			gap: 10rpx;
			:deep(.u-tag--primary) {
				background-color: #f4f5f6;
				border: none;
			}
			:deep(.u-tag--medium) {
				padding: 0 10rpx;
				line-height: 21px;
				height: 21px;
			}
			:deep(.u-tag__text--medium) {
				font-size: 12px;
			}
			:deep(.u-tag__text--primary) {
				color: black !important;
			}
		}
		.top-box {
			display: flex;
			justify-content: space-between;
			:deep(.u-tag--primary) {
				background-color: #f5f6f7;
				margin-left: 5px;
				line-height: 23px;
				border: 0;
			}
			:deep(.u-tag__text--primary) {
				color: #aaabae;
			}
			.title {
				color: rgba(0, 0, 0, 0.9);
				font-size: 14px;
				font-weight: 600;
				max-width: calc(100% - 100px);
			}
			.time {
				font-size: 12px;
				cursor: pointer;
				color: #333333;
			}
		}
		.bottom-text {
			color: #bbbbbb;
			font-size: 12px;
			.right {
				margin-left: 20rpx;
			}
		}
	}
}
</style>
